[bits 32]

section .text ; 代码段

global InByte ; 将inb标签导出，如果不导出，可重定位文件里没有这个符号，则在链接的时候会找不到符号
; 对应函数extern u8 inByte(u16 port);
InByte:
    push ebp ; 保存栈帧
    mov ebp, esp ; 将当前栈帧赋给ebp
    xor eax, eax ; 将eax置0
    mov edx, [ebp + 8] ; 获得端口号，赋给edx，在函数调用发起时，会将参数压入栈中，虽然参数是16字节，但也会4字节对齐
    in al, dx ; 将u16的端口号对应的8bit数据输入到al
    jmp $+2 ; 跳转到下一个指令，增加一点延迟，引入端口读入一般需要一些延迟，不过可以实现一些无延迟的函数，但这里为了简单好理解，直接增加些无用指令延迟
    jmp $+2
    jmp $+2
    leave ; 恢复栈帧，保存和恢复栈的操作是函数的基本模板
    ret

global OutByte 
; 对应函数extern void outByte(u16 port, u8 value);
OutByte:
    push ebp ; 保存栈帧
    mov ebp, esp ; 将当前栈帧赋给ebp
    mov edx, [ebp + 8] ; 获得端口号，赋给edx，在函数调用发起时，会将参数压入栈中，虽然参数是16字节，但也会4字节对齐
    mov eax, [ebp + 12] ; 传入参数的value，因为参数是从右往左压入的，显示value(更高地址)再是port(更低地址)
    out dx, al ; 将8bit al中的数据输出到dx对应的端口中
    jmp $+2 ; 跳转到下一个指令，增加一点延迟，引入端口读入一般需要一些延迟，不过可以实现一些无延迟的函数，但这里为了简单好理解，直接增加些无用指令延迟
    jmp $+2
    jmp $+2
    leave ; 恢复栈帧，保存和恢复栈的操作是函数的基本模板
    ret

global InWord ; 将inb标签导出，如果不导出，可重定位文件里没有这个符号，则在链接的时候会找不到符号
; 对应函数extern u16 inWord(u16 port)
InWord:
    push ebp ; 保存栈帧
    mov ebp, esp ; 将当前栈帧赋给ebp
    xor eax, eax ; 将eax置0
    mov edx, [ebp + 8] ; 获得端口号，赋给edx，在函数调用发起时，会将参数压入栈中，虽然参数是16字节，但也会4字节对齐
    in ax, dx ; 将u16的端口号对应的16bit数据输入到ax
    jmp $+2 ; 跳转到下一个指令，增加一点延迟，引入端口读入一般需要一些延迟，不过可以实现一些无延迟的函数，但这里为了简单好理解，直接增加些无用指令延迟
    jmp $+2
    jmp $+2
    leave ; 恢复栈帧，保存和恢复栈的操作是函数的基本模板
    ret

global OutWord 
; 对应函数extern void outWord(u16 port, u16 value)
OutWord:
    push ebp ; 保存栈帧
    mov ebp, esp ; 将当前栈帧赋给ebp
    mov edx, [ebp + 8] ; 获得端口号，赋给edx，在函数调用发起时，会将参数压入栈中，虽然参数是16字节，但也会4字节对齐
    mov eax, [ebp + 12] ; 传入参数的value，因为参数是从右往左压入的，显示value(更高地址)再是port(更低地址)
    out dx, ax ; 将16bit ax中的数据输出到dx对应的端口中
    jmp $+2 ; 跳转到下一个指令，增加一点延迟，引入端口读入一般需要一些延迟，不过可以实现一些无延迟的函数，但这里为了简单好理解，直接增加些无用指令延迟
    jmp $+2
    jmp $+2
    leave ; 恢复栈帧，保存和恢复栈的操作是函数的基本模板
    ret
